import mpPanelImg from '@/assets/image/screenshot/mp-panel.png';
import mpDataHarborImg from '@/assets/image/screenshot/mp-data-harbor.png';
import PlatformTag from '../components/PlatformTag'

# PageSpy API#api

## constructor()#constructor

Create a PageSpy instance.

- Type

  ```ts
  declare class PageSpy {
    constructor(config: InitConfig)
  }
  ```

  The constructor accepts a config object as an initialization parameter.

### config.api

Server address.

- Type: `string`

- Details

  - <PlatformTag type="browser" />

    The SDK automatically determines the server address api and the debug endpoint clientOrigin based on the import path. For example, if you include the SDK with `<script src="https://example.com/page-spy/index.min.js">`, the SDK will internally set:    
    - api: "example.com"
    - clientOrigin: "https://example.com"

    If your service is deployed elsewhere, you need to manually override this field.

  - <PlatformTag type="mp" /> <PlatformTag type="rn" /> <PlatformTag type="harmony" />

    This field is required.

### config.clientOrigin <PlatformTag type="browser" />
  
- Type: `string`

### config.project

Serves as a way to aggregate information and allows search in the debug room list.

- Type: `string`
- Default: 'default'

### config.title

A user-defined parameter that can help distinguish the current debugging client.

The corresponding information is displayed below the "Device ID" section on each debug connection panel.

- Type: `string`
- Default: '--'

### config.enableSSL

Manually specify the scheme for the PageSpy service.

- Type: `boolean`

- Details

  Pass a boolean value manually:

  - `true`: The SDK will access PageSpy services via `["https://", "wss://"]`.
  - `false`: The SDK will access PageSpy services via `["http://", "ws://"]`.

- <PlatformTag type="browser" />

  If not set, the SDK will automatically determine this value based on the page's URL.

  When the SDK cannot correctly determine the scheme, such as when imported through a browser extension like chrome-extension://xxx/sdk/index.min.js, it defaults to ["http://", "ws://"]. You can manually specify this field in such cases.

- <PlatformTag type="mp" /> <PlatformTag type="rn" /> <PlatformTag type="harmony" />

  These environments generally enforce HTTPS, so the default value is true. For development environments requiring HTTP, you can set it to false.

### config.disabledPlugins

PageSpy comes with built-in plugins ready to use. You can manually specify which plugins to disable.

- Type: `string[]`

### config.serializeData

Indicates whether the SDK should serialize non-primitive data types when collecting offline logs. Serialization facilitates easier review during replay.

- Type: `boolean`
- Default: `false`

### config.useSecret

Enable or disable authentication.

- Type: `boolean`
- Default: `false`
- Details:
  
  When enabled, the SDK generates a 6-digit random "secret key." This key must be entered when accessing the debug room.

### config.messageCapacity

Maximum number of cached data entries.

- Type: `number`
- Default: `1000`
- Details:

  Before the debug room is entered, the SDK caches data in memory. This allows the debug client to view historical data upon entering the room.

  Since the data size may grow, you can specify the maximum number of data records the SDK caches locally.

### config.dataProcessor

Customize data handling, allowing users to modify or ignore data.

- Type:
  ```ts
  declare interface DataProcessor {
    console?: (data: ConsoleData) => boolean;
    network?: (data: RequestItem) => boolean;
    storage?: (data: StorageData) => boolean;
    database?: (data: DatabaseData) => boolean;
    page?: (data: PageData) => boolean;
    system?: (data: SystemData) => boolean;
  }
  ```

- Details

  Processing functions correspond to built-in plugins. Users can directly modify the data within these functions. After execution, PageSpy processes the modified data. If a function returns false, the data will be ignored, meaning it won't appear in any debug mode.

  For more details, visit: https://www.pagespy.org/#/docs/changelog#v1_9_2

### config.disabledOnProd <PlatformTag type="mp" />

Disable PageSpy in production environments for Mini Programs.

- Type: `boolean`
- Default: `true`
- Details

  PageSpy is primarily intended for development and testing. It is not recommended for production environments, particularly for Mini Programs, where performance is more critical. Therefore, this field defaults to true.

### config.offline <PlatformTag type="browser" />

Offline mode.

- Type: `boolean`
- Default: `false`
- Details:

  With the offline replay functionality introduced in PageSpy@1.7.4, the integrated SDK can collect data and export offline logs without connecting to a debug client.

  Setting this to a truthy value enables "offline mode," where PageSpy does not create rooms or establish WebSocket connections.

  This is currently supported only in the browser environment.

### config.autoRender <PlatformTag type="browser" />

Indicates whether the SDK should automatically render a "white circular logo" control in the bottom-left corner after initialization.

- Type: `boolean`
- Default: `true`
- Details:

  If set to false, you can manually render using window.$pageSpy.render().

### config.logo <PlatformTag type="browser" />

Custom logo for the control rendering.

- Type: `string`

### config.primaryColor <PlatformTag type="browser" />

Set the theme color for modals and toasts.

- Type: `string`
- Default: `#8434e9`

### config.modal <PlatformTag type="browser" />

Configure the logo and title for the modal.

- Type:
  ```ts
  declare interface ModalConfig {
    logo?: string;
    title?: string;
  }
  ```

- Default:
  ```ts
  {
    logo: "<PageSpy LOGO>",
    title: "PageSpy"
  }
  ```

## registerPlugin()#registerPlugin

Static method, register a plugin.

- Type

  ```ts
  declare class PageSpy {
    static registerPlugin(plugin: PageSpyPlugin): void;
  }
  ```

- Details

  Call before `new PageSpy`, the parameter is an instance of a plugin that implements `PageSpyPlugin`. Each plugin instance should have a `name` attribute. If a plugin with the same name is registered multiple times, the plugin instance will only be registered once, and a warning message will be printed in the console.

- Example

  ```ts
  class DataHarbrPlugin implements PageSpyPlugin {
    name = 'DataHarborPlugin'

    ... // some code
  }

  PageSpy.registerPlugin(new DataHarborPlugin());

  // Repeated calls, the plugin will only be registered once
  PageSpy.registerPlugin(new DataHarborPlugin());
  ```

## pluginsWithOrder

List of registered plugins sorted by the `enforce` property of the plugin.

- Type

  ```ts
  declare class PageSpy {
    static plugins: Record<PluginOrder | 'normal', PageSpyPlugin[]>;
    static get pluginsWithOrder(): PageSpyPlugin[];
  }
  ```

- Details

  Each plugin should provide the `enforce: PluginOrder` attribute; if not provided, it defaults to `enforce: "normal"`. PageSpy will then maintain the plugin list in the order of `pre - normal - post`.

## updateRoomInfo()#updateRoomInfo

Update connection info after instantiation PageSpy.

- Type

  ```ts
  type UpdateConfig = {
    title?: string;
    project?: string;
  };

  declare class PageSpy {
    updateRoomInfo(obj: UpdateConfig): void;
  }
  ```

- Details

  The client identification information can be updated later through this method if it is not known when PageSpy is initialized.

- Example

  ```ts
  window.$pageSpy = new PageSpy({
    title: '--',
    project: '--',
  });

  async function YourCode() {
    const { title, project } = await xxx();

    window.$pageSpy.updateRoomInfo({
      title,
      project,
    });
  }
  ```

## abort()#abort

Abort the current PageSpy instance.

- Type

  ```ts
  declare class PageSpy {
    abort(): void;
  }
  ```

- Details

  PageSpy will disconnect, remove the relevant DOM from the document, clear the cached data, and call the `onReset()` method of all registered plugins.

  In the current context, APIs that are proxied or rewritten, such as `window.fetch` in the browser, will be restored to their state before PageSpy was instantiated.

- Example

  ```ts
  window.$pageSpy = new PageSpy(...);

  window.$pageSpy.abort();
  ```

## version

Current used version of PageSpy.

- Type

  ```ts
  declare class PageSpy {
    version: string;
  }
  ```

- Example

  ```ts
  window.$pageSpy = new PageSpy(...);

  console.log(window.$pageSpy.version);
  ```

## config

Configuration information. The configuration varies depending on the platform, such as `config.disableOnProd` which is specific to the mini-program end.

- Type

  ```ts
  declare class PageSpy {
    config: Config;
  }
  ```

## socketStore

Encapsulates the WebSocket instance, provides message event listeners, triggers callbacks upon receiving specified messages, and broadcasts messages.

- Type

  ```ts
  interface SocketStoreType {
    addListener(type: InteractiveType, fn: InteractiveEventCallback): void;
    addListener(type: InternalType, fn: InternalEventCallback): void;

    removeListener(type: InteractiveType, fn: InteractiveEventCallback): void;
    removeListener(type: InternalType, fn: InternalEventCallback): void;

    dispatchEvent(
      type: InteractiveType | InternalType,
      data: InteractiveEvent,
    ): void;
    dispatchEvent(type: InternalType, data: any): void;

    broadcastMessage(message: MessageItem, noCache?: boolean): void;
  }
  ```

- Details

  The first parameter of `addListener() / removeListener() / dispatchEvent()` is the message type, which we categorize into **"interactive"** and **"internal"** types.

  - **"InteractiveType"** message types are used to interact with the debugging client, for example: when the debugging client goes online, sends code to the client for execution, or clicks to expand object details, these will be sent to the SDK as message events, and the SDK will respond accordingly;
  - **"InternalType"** message types are currently used for interaction between plugins. For example, after each plugin generates data, it will dispatch an event through `socketStore.dispatchEvent('public-data')`, and the `DataHarborPlugin`, also a plugin, can process the data upon listening to this event.

  The `broadcastMessage()` broadcasts a message. The first parameter is the data sent from different plugins to the debugging end, and the second parameter `noCache` is used by the plugin to inform `socketStore` whether the current message being sent should be cached. The purpose of caching the data is so that when the debugging end "comes online," it can see historical messages, but not all data needs to be cached. For instance, when a client send a network request, whether it succeeds or fails, only the final state needs to be cached.

- Example

  ```ts
  // Please check the repository for the specific implementation of ConsolePlugin
  class ConsolePlugin implements PageSpyPlugin {
    onInit({ socketStore }) {
      socketStore.addListener('debug', ({ source }, reply) => {
        ...
      })

      socketStore.broadcastMessage(...)
    }
  }
  ```


#### showPanel() <PlatformTag type="mp" />

Show the debugging panel in miniprogram.

- Type:
  ```ts
  declare class PageSpy {
    showPanel(): void;
  }
  ```
- Details:

  <img src={mpPanelImg} style={{width: 375}} />

  This panel supports plugin registration of custom buttons, for example, if the [DataHarborPlugin](./offline-log#mp) is registered, a button of「Upload Offline Log」will appear in the panel:

  <img src={mpDataHarborImg} style={{width: 375}} />


